/**
 * \file packet_udp.c
 * \brief Packet UDP
 * \author Pierre Neumann / Julien Meutelet
 * \version 0.1
 * \date 20 decembre 2013
 *
 * Sert à Initialiser l'entête UDP et à l'afficher
 *
 */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h> 
#include <netinet/udp.h> 
#include <arpa/inet.h>

#include "packet_utils.h"
#include "packet_ip.h"
#include "packet_udp.h"

const size_t UDP_HEADER_SIZE = sizeof(struct udphdr); /*!< Taille de l'entête UDP */
const size_t UDP_PACKET_SIZE = sizeof(struct ip) + sizeof(struct udphdr) + sizeof("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); /*!< Taille d'un paquet UDP */
const int UDP_PROTOCOL_NUMBER = 17; /*!< Numéro du protocole UDP */

/**
 * \fn init_udp_header(char** packet, struct in_addr* destination, struct in_addr* source,int port,int ttl)
 * \brief Initialise un paquet UDP
 *
 * \param packet Chaine de caractère représentant le paquet UDP.
 * \param destination Pointeur vers la structure in_addr de la destination.
 * \param source Pointeur vers la structure in_addr de la source.
 * \param port Port sur lequel on souhaite envoyer le paquet.
 * \param ttl Entier utilisé pour initialiser le champ ttl de l'entête IP.
 * \return Rien.
 */
void init_udp_header(char** packet, struct in_addr* destination, struct in_addr* source,int port,int ttl){
	// On alloue la taille d'un paquet UDP
	*packet = (char *) malloc(UDP_PACKET_SIZE);  
	
	// On initialise un contenu pour le paquet 
	char* data = (char *)(*packet + sizeof(struct iphdr) + sizeof(struct udphdr));
    	strcpy(data , "ABCDEFGHIJKLMNOPQRSTUVWXYZ");

	// Initialisation de l'entête IP
	init_ip_header(packet,destination,source,UDP_HEADER_SIZE + strlen(data),UDP_PROTOCOL_NUMBER,ttl);
	
	// On complète les champs de l'entête UDP
	struct udphdr * hudp; 
	hudp = (struct udphdr *) (*packet + IP_HEADER_SIZE); 
	hudp->source = htons(1234); 
	hudp->dest = htons(port); 
	hudp->len = htons(UDP_HEADER_SIZE + strlen(data));
	hudp->check = 0; 
	// On calcule la checksum avec pseudo-header
	hudp->check = checksum_with_pseudoheader(packet,UDP_HEADER_SIZE + strlen(data));
}

/**
 * \fn print_udp_header(char** packet)
 * \brief Affiche l'entête UDP d'un paquet
 *
 * \param packet Chaine de caractère représentant le paquet UDP.
 * \return Rien.
 */
void print_udp_header(char** packet){
	struct udphdr *hudp = (struct udphdr *) (*packet + IP_HEADER_SIZE);
	printf("------Entête UDP------\n");
	printf("Port source : %u\n",ntohs(hudp->source));
	printf("Port destination : %u\n",ntohs(hudp->dest));
	printf("Longueur : %u\n",ntohs(hudp->len));
	printf("Checksum : %d\n",hudp->check);
}

